package com.fsquare.inventory.service.workflow;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.broadleafcommerce.core.order.domain.BundleOrderItem;
import org.broadleafcommerce.core.order.domain.DiscreteOrderItem;
import org.broadleafcommerce.core.order.domain.OrderItem;
import org.broadleafcommerce.core.order.service.workflow.CartOperationRequest;
import org.broadleafcommerce.core.workflow.BaseActivity;
import org.broadleafcommerce.core.workflow.ProcessContext;

import com.fsquare.inventory.domain.SkuInventory;
import com.fsquare.inventory.service.InventoryService;
import com.fsquare.inventory.service.InventoryUnavailableException;

/**
 * Workflow activity to check availability of inventory during cart operations.
 * 
 *
 * @author Rui Cunha (rcunha)
 */
public class CheckInventoryAvailabilityActivity  extends BaseActivity<ProcessContext<CartOperationRequest>> {
   

	
	@Resource(name = "fsquareInventoryService")
    protected InventoryService inventoryService;

    @Override
    public ProcessContext<CartOperationRequest> execute(ProcessContext<CartOperationRequest> context) throws Exception {
    	CartOperationRequest request = context.getSeedData();
    	
        HashMap<Long, Integer> skuQuantities = new HashMap<Long, Integer>();
        OrderItem orderItem = request.getOrderItem();
        
        if("wishlist".equals(request.getOrder().getName()))
        	return context;
        
        if (orderItem instanceof DiscreteOrderItem) {
            Long skuId = ((DiscreteOrderItem) orderItem).getSku().getId();
            skuQuantities.put(skuId, orderItem.getQuantity());
        } else if (orderItem instanceof BundleOrderItem) {
            BundleOrderItem bundleItem = (BundleOrderItem) orderItem;
            skuQuantities.put(bundleItem.getSku().getId(), bundleItem.getQuantity());
            List<DiscreteOrderItem> discreteItems = bundleItem.getDiscreteOrderItems();
            for (DiscreteOrderItem discreteItem : discreteItems) {
                Integer quantity = skuQuantities.get(discreteItem.getSku().getId());
                if (quantity == null) {
                    quantity = discreteItem.getQuantity();
                } else {
                    quantity += discreteItem.getQuantity();
                }
                skuQuantities.put(discreteItem.getSku().getId(), quantity);
            }
        } else {
            return context;
        }

        if (!skuQuantities.isEmpty()) {
            Set<Long> keys = skuQuantities.keySet();
            for (Long key : keys) {
                //Available inventory will not be decremented for this sku until checkout. This activity is assumed to be
                //part of the add to cart / update cart workflow
            	
            	SkuInventory inventory = inventoryService.getInventory(key);
            	Integer quantityAvailable = inventory.getQuantityAvailable();
            	
                boolean isQuantityAvailable = quantityAvailable >= skuQuantities.get(key);

                if (!isQuantityAvailable) {
                    String errorMessage = "Error: Sku with id of " + key + " does not have " + request.getAddedOrderItem().getQuantity() + " items in available inventory.";
                    throw new InventoryUnavailableException(errorMessage, key, skuQuantities.get(key), quantityAvailable);
                }
            }
        }
        
        return context;
    }

}
